# -*- coding: iso-8859-1 -*-
module TeXCheck

  load "TeXCheck.rb"
  class TeXFile
    def initialize(array)
      @bigArray = array
    end

    def self.load(reader, texfile)
      fail unless reader.class == MemoryReader || reader.class == FileReader
      fail unless texfile.class == String
      # TODO
      temparray = readAll(reader, texfile)
      return TeXFile.new(temparray)

    # Note: this is a class method! (i.e. a static method in java)
    # It is invoked using "TeXFile.load(...)" and it must return
    # a TeXFile-object.
    end

    def self.readAll(reader,texfile)
      numberoflineinthetexfile = 1
      texfile = self.makeViableForCall(texfile)
      temparray = reader.readlines(texfile)
      temparray2 = Array.new
      temparray3 = Array.new
      temparray.each do |lineofarray|
        if lineofarray =~ /\\input{(\w+)/ then
        temp2texfile = self.makeViableForCall($1)
        temparray3 += self.readAll(reader, temp2texfile)
        else
          location = Location.new(texfile, numberoflineinthetexfile)
          line = Line.new(lineofarray, location)
          puts "runtime succeeded of #{numberoflineinthetexfile.to_s} in "+ texfile
        temparray3 << line
        end
        numberoflineinthetexfile += 1
      end
      return temparray3
    end

    def self.makeViableForCall(texfile)
      if texfile[(texfile.length-4)..(texfile.length)] != ".tex" then
        texfile += ".tex"
      end
      return texfile
    end

    def lines
      # TODO
      return @bigArray

    # Must return the LaTeX document in linearized form
    # (an array of Line-objects)
    end
  end

  class Checker
    SINGLE_FILE = false
    def check(tex)
      fail unless tex.class == TeXFile
      errors = Array.new
      lines = tex.lines
      # checking for invalid characters
      lines.each do |line|
        line.contents.split(//).each do |c|
          if c.ord> 127 then
            errors <<  InvalidCharacterError.new(line)
          end
        end
      end
      # checking for missing labels
      lines.each do |line|
        if line.contents =~ /\\begin\{(definition|theorem)\}\[(\w+)?\]/ then
          if not line.contents =~ /\\label\{(\w|:)+\}/ then
            errors << MissingLabelError.new(line)
          end
        end
      end
      # checking on invalid labels
      lines.each do |line|
        if line.contents =~ /\\begin\{definition\}\[(\w+)?\]/ then
           #if not line.contents =~ /\\label\{def\:(\w+)\}/ then
            errors << InvalidLabelError.new(line) unless line.contents =~ /\\label\{def\:(\w+)\}/
          #end
        elsif line.contents =~ /\\begin\{theorem\}\[(\w+)?\]/ then
           #if not line.contents =~ /\\label\{thm\:(\w+)\}/ then
            errors << InvalidLabelError.new(line) unless line.contents =~ /\\label\{thm\:(\w+)\}/
          #end
          
        end
      end
      # checking for duplicate labels
      labelarray = Array.new
      lines.each do |line|
        if line.contents =~ /\\label\{(def:|thm:)(\w+)\}/ then
          if labelarray.index($1+$2+"") == nil then
            labelarray << $1+$2+""
          else
            errors << DuplicateLabelError.new(line)
          end
        end
      end
      # checking if all labels exist
      unknownlabelArray = Array.new
      lines.each do |line|
        if line.contents =~ /\\ref\{(def:|thm:)(\w+)\}/ then
          if labelarray.index($1+$2+"") == nil then
            errors << UnknownLabelError.new(line)
            unknownlabelArray << $1+$2+""
          end
        end
      end
      #checking for forward references
      labelandrefarray = Array.new
      lines.each do |line|
        if line.contents =~ /\\begin\{(definition|theorem)\}\[(\w+)?\] \\label\{(def:|thm:)(\w+)\}/ then
          labelandrefarray << $3+$4+""
        elsif line.contents =~ /\\ref\{(def:|thm:)(\w+)\}/ then
          if labelandrefarray.index($1+$2+"") == nil then
            errors << ForwardReferenceError.new(line)
            labelandrefarray << $1+$2+""
          elsif not unknownlabelArray.index($1+$2+"") == nil then
            errors << ForwardReferenceError.new(line)
            labelandrefarray << $1+$2+""
          end
        end
      end
      #return all errors
      return errors
    end
  end
end